package com.tianlang.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import com.tianlang.cache.AuthorityCache;
import com.tianlang.domain.pojo.Authority;
import com.tianlang.security.tool.AntUrlPathMatcher;
import com.tianlang.security.tool.UrlMatcher;
import com.tianlang.service.IAuthorityManager;

/**
 * 最核心的地方，就是提供某个资源对应的权限定义，即getAttributes方法返回的结果。 此类在初始化时，应该取到所有资源及其对应角色的定义。
 * 自定义资源与权限对应关系 此类在初始化时，应该取到所有资源及其对应角色的定义
 * 
 * @author mchp
 */
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

	private UrlMatcher urlMatcher = new AntUrlPathMatcher();;
	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
	private IAuthorityManager authorityManager;

	public MySecurityMetadataSource(IAuthorityManager authorityManager) {
		this.authorityManager = authorityManager;
		loadResourceDefine();
	}

	/**
	 * 加载权限资源
	 */
	public void loadResourceDefine() {
		Map<String, List<Authority>> map = authorityManager.loadAll();
		AuthorityCache.Authority_Map = map;
		resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
		Set<String> keySet = map.keySet();
		for (String key : keySet) {
			Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
			List<Authority> list = map.get(key);
			for (Authority authority : list) {
				ConfigAttribute ca = new SecurityConfig(authority.getRoleName());
				atts.add(ca);
			}
			resourceMap.put(key, atts);
		}
	}

	// 根据URL，找到相关的权限配置。
	@Override
	public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
		String url = ((FilterInvocation) object).getRequestUrl();
		Integer end = url.lastIndexOf(".");
		if (end != -1) {
			url = url.substring(0, end);
		}
		end = url.lastIndexOf("?");
		if (end != -1) {
			url = url.substring(0, end);
		}
		Iterator<String> ite = resourceMap.keySet().iterator();
		while (ite.hasNext()) {
			String resURL = ite.next();
			if (urlMatcher.pathMatchesUrl(resURL, url)) {
				return resourceMap.get(resURL);
			}
		}
		return null;
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return false;
	}

}